import { useEffect, useState } from 'react'


import '@tensorflow/tfjs-backend-cpu';
import '@tensorflow/tfjs-backend-webgl';

//import * as mobilenet from '@tensorflow-models/mobilenet';
import { MobileNet } from './classifier/mobilenet';
import { MobileNetV3, MobileNetV3Small } from './MobileNetV3';
import { KNNClassifier } from './classifier/KNNClassifier';


export const classifier = new KNNClassifier();

import * as tf from '@tensorflow/tfjs';

import VConsole from 'vconsole';
new VConsole();
import './App.css'

function App() {
  const [imgUrl, setImageUrl] = useState('faces/Sarah_Chalke_thumb.jpg');
  const [out, setOut] = useState(['']);

  const [model, setModel] = useState<MobileNet | null>(null);

  const [image, setImage] = useState<HTMLImageElement | null>(null);
  const [canvas, setCanvas] = useState<HTMLCanvasElement | null>(null);



  useEffect(() => {
    console.log('--', Date.now());
    const eleCanvas = document.getElementById('canvas');
    if (eleCanvas instanceof HTMLCanvasElement) {
      setCanvas(eleCanvas);
      console.log('canvas', eleCanvas);
    }
    let eleImg = document.getElementById('img');
    if (eleImg instanceof HTMLImageElement) {
      setImage(eleImg);
      console.log('eleImg', eleImg);
    }
  }, []);


  const output = (args: string) => {
    out.push(args);
    setOut(out.concat([]));
  };


  const infer = async () => {
    output('infer begin')
    //console.log('infer:', image, canvas);
    if (image && canvas) {
      //let r = model.infer(image, true);
      //console.log('infer true', r);
      let tensor = tf.browser.fromPixels(image, 1);
      //console.log('tensor', tensor);

      tf.browser.toPixels(tensor, canvas);


    } else {
      output('infer end do nothing')
    }
  }

  const train = () => {
    const input1 = tf.input({ shape: [85, 170, 3] });
    const dense1 = tf.layers.dense({ units: 3 }).apply(input1);
    const output = tf.layers.dense({ units: 1, activation: 'softmax' }).apply(dense1);

    if (output instanceof tf.SymbolicTensor) {
      console.log('v3', Date.now());
      let model = new MobileNetV3Small({inputs:[],outputs:[]});
      //model.build([null, 224, 224, 3])
      //model.build([null, 85, 170, 3])
      model.summary()
      model.compile({ optimizer: 'sgd', loss: 'meanSquaredError' });

      if (image) {
        //model.infer(image, true);
      }
    }
  }

  const classify = async () => {
    if (model && image) {
      let array = await model.classify(image, 3);
      console.log(array);
    } else {
      output('classify end do nothing')
    }
  }

  const load = async () => {

    output('loading')
    //let net = await MobileNet.load('https://tfhub.dev/google/imagenet/mobilenet_v1_100_224/classification/1/model.json?tfjs-format=file');
    //let net = await MobileNet.load('https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/classification/2/model.json?tfjs-format=file');
    let net = await MobileNet.load('indexeddb://MobileNet');
    setModel(net);
    output('finally')
    /*
    mobilenet.load().then((net) => {
    }).catch((reason: any) => {
      output('catch' + reason)
    }).finally(() => {
      output('finally')
    });
    */
  }
  const save = async () => {
    output('save');
    model?.save();
  }


  return (
    <div className='barcode-scanner-modal'>
      <button onClick={() => { setOut([]) }}>clean</button>
      <button onClick={() => load()}>load</button>
      <button onClick={() => save()}>save</button>
      <button onClick={() => infer()}>infer</button>
      <button onClick={() => classify()}>classify</button>
      <button onClick={() => train()}>train</button>
      <br />
      <select onChange={(a) => {
        console.log(a.currentTarget.value);
        setImageUrl(a.currentTarget.value)
      }}>
        <option></option>
        <option>faces/Sarah_Chalke_thumb.jpg</option>
        <option>faces/Milla_Jovovich_thumb.jpg</option>
        <option>faces/Gene_Hackman_thumb.jpg</option>
      </select>
      <div>
        <img id='img' src={imgUrl}></img>
      </div>
      <div>
        <canvas id='canvas'></canvas>
      </div>
      <div>{out.map((item, i) => (<ol key={i}>#{item}</ol>))}</div>
    </div>
  )
}

export default App
